package com.basker.pisces.service.dto;

import org.springframework.beans.BeanUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

/**
 * 工厂类，用于方便创建{@link IServiceResult}实例。
 *
 * @author hangwen
 */
public class ServiceResultFactory {

    private static final String DEFAULT_OK_MESSAGE = "ok";
    private static final String DEFAULT_ERROR_MESSAGE = "error";

    /**
     * 外部无法传入泛型参数时，调用该方法创建result对象
     *
     * @param resultClass
     * @param result
     * @param reasonCode
     * @param message
     * @param data
     * @return
     */
    public static IServiceResult<?> build(@Nullable Class<?> resultClass, int status, String message, Object data) {
        return create(resultClass, status, message, data);
    }

    /**
     * 用一个已有的结果创建新结果，忽略data属性，消除泛型约束用
     *
     * @param result
     * @return
     */
    public static <TData> DefaultServiceResult<TData> build(IServiceResult<?> result) {
        return create(null, result.getStatus(), result.getMessage(), null);
    }

    /**
     * 创建一个表示错误的结果
     *
     * @param resultClass 结果对象的类型
     * @param status      错误结果状态码
     * @param message     消息
     * @return resultClass的实例
     */
    public static <TResult extends IServiceResult<TData>, TData> TResult error(Class<TResult> resultClass, int status,
                                                                               String message) {
        assertErrorStatus(status);
        return create(resultClass, status, message, null);
    }

    /**
     * 创建一个表示错误的结果
     *
     * @param resultClass 结果对象的类型
     * @param status      错误结果状态码
     * @param message     消息
     * @param data        业务对象
     * @return resultClass的实例
     */
    public static <TResult extends IServiceResult<TData>, TData> TResult error(Class<TResult> resultClass, int status,
                                                                               String message, TData data) {
        assertErrorStatus(status);
        return create(resultClass, status, message, data);
    }

    /**
     * 创建一个表示错误的结果
     *
     * @param resultClass 结果对象的类型
     * @param message     消息
     * @return resultClass的实例
     */
    public static <TResult extends IServiceResult<TData>, TData> TResult error(Class<TResult> resultClass,
                                                                               String message) {
        return create(resultClass, IServiceResult.FAILURE_STATUS, message, null);
    }

    /**
     * 创建一个表示错误的结果
     *
     * @param resultClass 结果对象的类型
     * @param message     消息
     * @param data        业务对象
     * @return resultClass的实例
     */
    public static <TResult extends IServiceResult<TData>, TData> TResult error(Class<TResult> resultClass,
                                                                               String message, TData data) {
        return create(resultClass, IServiceResult.FAILURE_STATUS, message, data);
    }

    /**
     * 创建一个表示错误的结果
     *
     * @param resultClass 结果对象的类型
     * @param data        业务对象
     * @return resultClass的实例
     */
    public static <TResult extends IServiceResult<TData>, TData> TResult error(Class<TResult> resultClass, TData data) {
        return create(resultClass, IServiceResult.FAILURE_STATUS, DEFAULT_ERROR_MESSAGE, data);
    }

    /**
     * 创建一个表示错误的结果
     *
     * @param result  错误结果状态码
     * @param message 消息
     * @return DefaultServiceResult实例
     */
    public static <TData> DefaultServiceResult<TData> error(int status, String message) {
        assertErrorStatus(status);
        return create(null, status, message, null);
    }

    /**
     * 创建一个表示错误的结果
     *
     * @param status  错误结果状态码
     * @param message 消息
     * @param data    业务对象
     * @return
     */
    public static <TData> DefaultServiceResult<TData> error(int status, String message, TData data) {
        assertErrorStatus(status);
        return create(null, status, message, data);
    }

    /**
     * 创建一个表示错误的结果
     *
     * @param message 消息
     * @return DefaultServiceResult实例
     */
    public static <TData> DefaultServiceResult<TData> error(String message) {
        return create(null, IServiceResult.FAILURE_STATUS, message, null);
    }

    /**
     * 创建一个表示错误的结果
     *
     * @param message 消息
     * @param data    业务对象
     * @return DefaultServiceResult实例
     */
    public static <TData> DefaultServiceResult<TData> error(String message, TData data) {
        return create(null, IServiceResult.FAILURE_STATUS, message, data);
    }

    /**
     * 创建一个表示错误的结果
     *
     * @param data 业务对象
     * @return DefaultServiceResult实例
     */
    public static <TData> DefaultServiceResult<TData> error(TData data) {
        return create(null, IServiceResult.FAILURE_STATUS, DEFAULT_ERROR_MESSAGE, data);
    }

    public static <D> DefaultServiceResult<D> noData(Object id) {
        return ServiceResultFactory.error("No data found,id:" + id + "!");
    }

    /**
     * 创建一个表示成功的结果
     *
     * @return
     */
    public static DefaultServiceResult<Void> ok() {
        return ok(DEFAULT_OK_MESSAGE);
    }

    /**
     * 创建一个表示成功的结果
     *
     * @param resultClass 结果对象的类型
     * @param message     消息
     * @return resultClass的实例
     */
    public static <TResult extends IServiceResult<TData>, TData> TResult ok(Class<TResult> resultClass,
                                                                            String message) {
        return create(resultClass, IServiceResult.SUCCESS_STATUS, message, null);
    }

    /**
     * 创建一个表示成功的结果
     *
     * @param resultClass 结果对象的类型
     * @param message     消息
     * @param data        业务对象
     * @return resultClass的实例
     */
    public static <TResult extends IServiceResult<TData>, TData> TResult ok(Class<TResult> resultClass, String message,
                                                                            TData data) {
        return create(resultClass, IServiceResult.SUCCESS_STATUS, message, data);
    }

    /**
     * 创建一个表示成功的结果
     *
     * @param resultClass 结果对象的类型
     * @param data        业务对象
     * @return resultClass的实例
     */
    public static <TResult extends IServiceResult<TData>, TData> TResult ok(Class<TResult> resultClass, TData data) {
        return create(resultClass, IServiceResult.SUCCESS_STATUS, DEFAULT_OK_MESSAGE, data);
    }

    /**
     * 创建一个表示成功的结果
     *
     * @param message 消息
     * @return DefaultServiceResult实例
     */
    public static <TData> DefaultServiceResult<TData> ok(String message) {
        return create(null, IServiceResult.SUCCESS_STATUS, message, null);
    }

    /**
     * 创建一个表示成功的结果
     *
     * @param message 消息
     * @param data    业务对象
     * @return DefaultServiceResult实例
     */
    public static <TData> DefaultServiceResult<TData> ok(String message, TData data) {
        return create(null, IServiceResult.SUCCESS_STATUS, message, data);
    }

    /**
     * 创建一个表示成功的结果
     *
     * @param data 业务对象
     * @return DefaultServiceResult实例
     */
    public static <TData> DefaultServiceResult<TData> ok(TData data) {
        return create(null, IServiceResult.SUCCESS_STATUS, DEFAULT_OK_MESSAGE, data);
    }

    private static void assertErrorStatus(int status) {
        Assert.isTrue(status != IServiceResult.SUCCESS_STATUS, "parameter 'status' 0 is not an error status!");
    }

    private static <TResult extends IServiceResult<TData>, TData> TResult create(@Nullable Class<?> resultClass,
                                                                                 int status, String message, TData data) {
        resultClass = resultClass != null ? resultClass : DefaultServiceResult.class;

        Assert.isTrue(IServiceResult.class.isAssignableFrom(resultClass),
                "parameter 'resultClass' must be IServiceResult");

        @SuppressWarnings("unchecked")
        TResult serviceResult = (TResult) BeanUtils.instantiateClass(resultClass, IServiceResult.class);

        serviceResult.setStatus(status);
        serviceResult.setMessage(message);
        serviceResult.setData(data);

        return serviceResult;
    }

}
